跳到主要内容

Unity 加载资源与存储数据

DontDestroyOnLoad

参考资料 Unity中DontDestroyOnLoad在切换场景时的坑点

DontDestroyOnLoad 可以保证 Gameobject 以及上面绑定的组件不会销毁,在处理全局控制的时候有用。

public class ExampleClass :MonoBehaviour{
void Awake() {
DontDestroyOnLoad(gameObject);
}
}

运行时就会把这个对象丢到 DontDestroyOnLoad 这里

image.png

但是要注意使用 DontDestroyOnLoad 的时候需要注意的坑:

由于使用 DontDestroyOnLoad 的物体不会被释放掉,假设我们写了上面的代码,而物体所在的游戏场景又可以重复进入的时候,游戏物体就会在每次进入场景的时候创建一次,甚至可以无限创建下去,这样的处理明显不妥。

针对性的解决方案:(注意不可以在 Unity 里面使用静态构造方法的方式实例对象)

判断一下引用是否为空,如果为空再设置为 DontDestroyOnLoad,如果不为空则删除此游戏物体

public class GameManager : MonoBehaviour
{
public static GameManager Instance { get; set; }//单例

private void Awake()
{
if (Instance != null)
{
Destroy(gameObject);
}
else
{
Instance = this;
DontDestroyOnLoad(this);
}
}
}

Unity 加载资源

参考资料 unity3d Resources.Load动态加载资源

Unity3d 常用两种加载资源方案:Resources.LoadAssetBundle

Resources.Load 加载资源

官方文档使用 Resources.Load

使用这种方式加载资源,首先需要下 Asset 目录下创建一个名为 Resources 的文件夹,这个命名是 Unity 规定的方式,然后把资源文件放进去,

当然也可以在 Resources 中再创建子文件夹,当然在代码加载时需要添加相应的资源路径

using UnityEngine;
using System.Collections;

public class LoadResDemo : MonoBehaviour {

// 这里的根路径就是 Resources 目录
private string cubePath = "Prebs/MyCubePreb"; // Asset/Resources/Prebs/MyCubePreb
private string spherePath = "MySpherePreb"; // Asset/Resources/MySpherePreb
void Start () {
//把资源加载到内存中
Object cubePreb = Resources.Load(cubePath, typeof(GameObject));
//用加载得到的资源对象,实例化游戏对象,实现游戏物体的动态加载
GameObject cube = Instantiate(cubePreb) as GameObject;



//以下同理实现Sphere的动态实例化
//把资源加载到内存中
Object spherePreb = Resources.Load(spherePath, typeof(GameObject));
//用加载得到的资源对象,实例化游戏对象,实现游戏物体的动态加载
GameObject sphere = Instantiate(spherePreb) as GameObject;
}

void Update () {

}
}

注意!! Resources.Load 加载资源不用加文件后缀

// 加载 Assets/Resources/TileSprite/TileSpriteAtlas.asset
// 不用加文件后缀
SpriteLibraryAsset sa = Resources.Load<SpriteLibraryAsset>("TileSprite/TileSpriteAtlas");

加载 JSON 文件

public string JsonRead(string name)
{
string json = "";
TextAsset text = Resources.Load<TextAsset>("Jsons/" + name);
json = text.text;
if (string.IsNullOrEmpty(json)) return null;
return json;
}

获取文件路径

一般存档之类的文件丢到这个 Application.persistentDataPath 目录里面来

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class GameSaveManager : MonoBehaviour
{
public Inventory myInventory;

void Awake()
{
SaveGame();
}

public void SaveGame()
{
Debug.Log(Application.persistentDataPath);
// 如果不存在则创建目录
if (!Directory.Exists(Application.persistentDataPath + "/game_SaveData"))
{
Directory.CreateDirectory(Application.persistentDataPath + "/game_SaveData");
}
}
}

创建资源路径

AssetDatabase.GetAssetPath 获取资源路径

@MenuItem("GameObject/Create Material")
static function CreateMaterial () {
//新建一个简单的材质资源
var material = new Material (Shader.Find("Specular"));
// 创建一个资源到 Assets 目录下面
AssetDatabase.CreateAsset(material, "Assets/MyMaterial.mat");

//打印新建资源的路径
Debug.Log(AssetDatabase.GetAssetPath(material));
}

Unity 场景管理

参考资料 Unity 通用场景管理器分享 参考资料 【Unity】场景管理/切换:SceneManager、GetScene、LoadScene、MoveGameObjectToScene等

首先别忘了把当前场景添加到 Build Settings 里面

image.png

重新加载场景

GetActiveScene 是取得当前已经激活的场景

SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);

ScriptableObject 保存数据

参考资料 ScriptableObject

ScriptableObject 是一个可独立于类实例来保存大量数据的数据容器。ScriptableObjects 的一个主要用例是通过避免重复值来减少项目的内存使用量。如果项目有一个预制件在附加的 MonoBehaviour 脚本中存储不变的数据,这将非常有用。

每次实例化预制件时,都会产生单独的数据副本。这种情况下可以不使用该方法并且不存储重复数据,而是使用 ScriptableObject 来存储数据,然后通过所有预制件的引用访问数据。这意味着内存中只有一个数据副本。

// 即,继承的不是 MonoBehaviour 而是 ScriptableObject
// 这个 fileName 是创建的资源默认名字
[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/New Item", order = 1)]
public class Item : ScriptableObject // 继承的不是 MonoBehaviour
{
...
}

与 MonoBehaviour 类似,ScriptableObjects 派生自 Unity 基对象,但不同于 MonoBehaviour 之处在于,不能将 ScriptableObject 附加到 GameObject。而是应该将它们保存为项目中的资源。

ScriptableObjects 的主要用例为:

  • 在 Editor 会话期间保存和存储数据
  • 将数据保存为项目中的资源,以便在运行时使用

要使用 ScriptableObject,创建一个脚本,并使其继承自 ScriptableObject 类(然后无需让它挂载在任何的空物体上)。可以使用 CreateAssetMenu 属性,从而使用这个的类轻松创建自定义资源。例如:

[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/New Item")]
public class Item : ScriptableObject
{
public string itemName;
public Sprite itemImage; //渲染的精灵
public int itemHeld; //当前Item的数量
[TextArea] // 如果当描述信息很多的时候可以用这个属性,让它变成一个文本框(它还有其它的属性,最大行数,最小行数)
public string itemInfo;
public bool equip; // 当前物品是否可装备
}

然后在资源菜单就可以看到这个创建资源的选项

这个创建的资源如下所示:

使用 LitJson 处理 JSON 数据

首先到官网下载这个 dll 文件(可以使用其它的 JSON 工具)

下载 地址(默认浏览器会拦截 dll 文件,下载后注意是否被拦截了)

将下载的 dll 文件拖拽到 Unity的 Plugins 文件夹下面(自己创建)

JSON 文件如下

{
"age" : [1,2,3,4],
"map" : [[1,2,3],[4,5,6]]
}

使用方法

//获取Json中的文本。文本在unity中是 TextAsset 类型,文件无需加后缀
TextAsset jsonText = Resources.Load<TextAsset>("Jsons/mapData");
//把json文本转换为 jsonData格式
JsonData itemData = JsonMapper.ToObject(jsonText.text);

int[] ages = (int[])itemData["age"] // [1,2,3,4]
int a = itemData["map"][1][2] // 6